﻿using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Util.Ui.NgZorro.Components.Base;
using Util.Ui.NgZorro.Components.Upload.Helpers;
using Util.Ui.NgZorro.Components.Upload.Renders;
using Util.Ui.NgZorro.Enums;
using Util.Ui.Renders;

namespace Util.Ui.NgZorro.Components.Upload; 

/// <summary>
/// 上传,生成的标签为&lt;nz-upload>&lt;/nz-upload>
/// </summary>
[HtmlTargetElement( "util-upload" )]
public class UploadTagHelper : FormControlContainerTagHelperBase {
    /// <summary>
    /// 配置
    /// </summary>
    private Config _config;
    /// <summary>
    /// 扩展属性,属性表达式
    /// </summary>
    public ModelExpression For { get; set; }
    /// <summary>
    /// 扩展属性,[(model)],模型双向绑定
    /// </summary>
    public string NgModel { get; set; }
    /// <summary>
    /// 扩展属性,是否启用扩展指令
    /// </summary>
    public bool EnableExtend { get; set; }
    /// <summary>
    /// 扩展属性 [isClearFiles],是否清除文件列表
    /// </summary>
    public string ClearFiles { get; set; }
    /// <summary>
    /// 扩展属性 [modelToFilesDebounceTime],模型数据转换为上传文件列表的延迟时间,单位:毫秒,默认值: 100
    /// </summary>
    public string ModelToFilesDebounceTime { get; set; }
    /// <summary>
    /// 扩展属性 [required],是否必填项
    /// </summary>
    public string Required { get; set; }
    /// <summary>
    /// 扩展属性 requiredMessage,必填项验证消息
    /// </summary>
    public string RequiredMessage { get; set; }
    /// <summary>
    /// 扩展属性 [requiredMessage],必填项验证消息
    /// </summary>
    public string BindRequiredMessage { get; set; }
    /// <summary>
    /// nzAccept,接受上传的文件类型,范例: '.doc,.docx,application/msword'
    /// </summary>
    public string Accept { get; set; }
    /// <summary>
    /// [nzAccept],接受上传的文件类型,范例: '.doc,.docx,application/msword'
    /// </summary>
    public string BindAccept { get; set; }
    /// <summary>
    /// nzAction,上传地址,必选参数,类型: string | ((file: NzUploadFile) => string | Observable&lt;string>)
    /// </summary>
    public string Action { get; set; }
    /// <summary>
    /// [nzAction],上传地址,必选参数,类型: string | ((file: NzUploadFile) => string | Observable&lt;string>)
    /// </summary>
    public string BindAction { get; set; }
    /// <summary>
    /// [nzDirectory],是否支持上传文件夹,默认值: false
    /// </summary>
    public string Directory { get; set; }
    /// <summary>
    /// [nzBeforeUpload],上传前钩子函数,参数为上传的文件，返回 false 停止上传,注意：务必使用 => 定义处理方法,函数定义: (file: NzUploadFile, fileList: NzUploadFile[]) => boolean | Observable&lt;boolean>
    /// </summary>
    public string BeforeUpload { get; set; }
    /// <summary>
    /// [nzCustomRequest],自定义上传实现,覆盖默认上传行为，注意：务必使用 => 定义处理方法,函数定义: (item) => Subscription
    /// </summary>
    public string CustomRequest { get; set; }
    /// <summary>
    /// [nzData],上传参数,可以是返回上传参数的方法，注意：务必使用 => 定义处理方法,类型: Object | ((file: NzUploadFile) => Object | Observable&lt;{}>)
    /// </summary>
    public string Data { get; set; }
    /// <summary>
    /// [nzDisabled],是否禁用
    /// </summary>
    public string Disabled { get; set; }
    /// <summary>
    /// [nzFileList],文件列表,类型: NzUploadFile[]
    /// </summary>
    public string FileList { get; set; }
    /// <summary>
    /// [(nzFileList)],文件列表,类型: NzUploadFile[]
    /// </summary>
    public string BindonFileList { get; set; }
    /// <summary>
    /// 扩展属性,不自动设置 nzFileList 文件列表
    /// </summary>
    public bool NotBindFileList { get; set; }
    /// <summary>
    /// [nzLimit],限制单次最多上传数量,nzMultiple 打开时有效,0 表示不限,默认值: 0
    /// </summary>
    public string Limit { get; set; }
    /// <summary>
    /// [nzSize],限制文件大小,单位：KB,0 表示不限,默认值: 0
    /// </summary>
    public string Size { get; set; }
    /// <summary>
    /// nzFileType,限制文件类型,范例: image/png,image/jpeg,image/gif,image/bmp
    /// </summary>
    public string FileType { get; set; }
    /// <summary>
    /// [nzFileType],限制文件类型,范例: image/png,image/jpeg,image/gif,image/bmp
    /// </summary>
    public string BindFileType { get; set; }
    /// <summary>
    /// [nzFilter],自定义过滤器,类型: UploadFilter[]
    /// </summary>
    public string Filter { get; set; }
    /// <summary>
    /// [nzHeaders],设置上传的请求头部,类型: Object | ((file: NzUploadFile) => Object | Observable&lt;{}>),范例: { authorization: 'authorization-text' }
    /// </summary>
    public string Headers { get; set; }
    /// <summary>
    /// nzListType,上传列表的内建样式,可选值: 'text' | 'picture' | 'picture-card',默认值: 'text'
    /// </summary>
    public UploadListType ListType { get; set; }
    /// <summary>
    /// [nzListType],上传列表的内建样式,可选值: 'text' | 'picture' | 'picture-card',默认值: 'text'
    /// </summary>
    public string BindListType { get; set; }
    /// <summary>
    /// [nzMultiple],是否支持多选文件,开启后按住 ctrl 可选择多个文件,默认值: false
    /// </summary>
    public string Multiple { get; set; }
    /// <summary>
    /// nzName,发送到服务端的文件参数名,默认值: 'file'
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// [nzName],发送到服务端的文件参数名,默认值: 'file'
    /// </summary>
    public string BindName { get; set; }
    /// <summary>
    /// [nzShowUploadList],是否显示上传列表,类型: boolean | { showPreviewIcon?: boolean, showRemoveIcon?: boolean, showDownloadIcon?: boolean },默认值: true
    /// </summary>
    public string ShowUploadList { get; set; }
    /// <summary>
    /// [nzShowButton],是否显示上传按钮,默认值: true
    /// </summary>
    public string ShowButton { get; set; }
    /// <summary>
    /// [nzWithCredentials],上传时是否携带cookie,默认值: false
    /// </summary>
    public string WithCredentials { get; set; }
    /// <summary>
    /// [nzOpenFileDialogOnClick],点击是否打开文件对话框,默认值: true
    /// </summary>
    public string OpenFileDialogOnClick { get; set; }
    /// <summary>
    /// [nzPreview],点击文件链接或点击预览图标时的回调函数,注意：务必使用 => 定义处理方法,类型: (file: NzUploadFile) => void
    /// </summary>
    public string Preview { get; set; }
    /// <summary>
    /// [nzPreviewFile],自定义文件预览实现函数,注意：务必使用 => 定义处理方法,类型: (file: NzUploadFile) => Observable&lt;dataURL: string>
    /// </summary>
    public string PreviewFile { get; set; }
    /// <summary>
    /// [nzPreviewIsImage],预览文件是否有效图片函数,用于图片URL为非标准格式,注意：务必使用 => 定义处理方法,类型: (file: NzUploadFile) => boolean
    /// </summary>
    public string PreviewIsImage { get; set; }
    /// <summary>
    /// [nzRemove],点击移除文件时的回调函数,返回值为 false 不移除,注意：务必使用 => 定义处理方法,类型: (file: NzUploadFile) => boolean | Observable&lt;boolean>
    /// </summary>
    public string Remove { get; set; }
    /// <summary>
    /// [nzDownload],点击下载文件时的回调函数,如果没有指定，则默认跳转到文件 url 对应的标签页,类型: (file: NzUploadFile) => void
    /// </summary>
    public string Download { get; set; }
    /// <summary>
    /// [nzTransformFile],在上传之前转换文件函数,类型: (file: NzUploadFile) => NzUploadTransformFileType
    /// </summary>
    public string TransformFile { get; set; }
    /// <summary>
    /// [nzIconRender],图标渲染模板,自定义显示图标,类型: TemplateRef&lt;{ $implicit: NzUploadFile }>
    /// </summary>
    public string IconRender { get; set; }
    /// <summary>
    /// [nzFileListRender],文件列表渲染模板,自定义显示整个列表,类型: TemplateRef&lt;{ $implicit: NzUploadFile[] }>
    /// </summary>
    public string FileListRender { get; set; }
    /// <summary>
    /// 扩展属性 *nzSpaceItem,值为true时设置为间距项,放入 nz-space 组件中使用
    /// </summary>
    public bool SpaceItem { get; set; }
    /// <summary>
    /// (nzChange),上传文件改变事件,类型: EventEmitter&lt;NzUploadChangeParam>
    /// </summary>
    public string OnChange { get; set; }
    /// <summary>
    /// 扩展事件 (modelChange),模型变更事件
    /// </summary>
    public string OnModelChange { get; set; }
    /// <summary>
    /// 扩展事件 (onUploadComplete),上传完成事件,全部文件上传完成时触发,类型: EventEmitter&lt;any>,参数为模型数据model
    /// </summary>
    public string OnUploadComplete { get; set; }

    /// <inheritdoc />
    protected override void ProcessBefore( TagHelperContext context, TagHelperOutput output ) {
        _config = new Config( context, output );
        var service = new UploadService( _config );
        service.Init();
    }

    /// <inheritdoc />
    protected override IRender GetRender( TagHelperContext context, TagHelperOutput output, TagHelperContent content ) {
        _config.Content = content;
        return new UploadRender( _config );
    }
}